// Door Triggers - these triggers will see if they have a variable assigned
// to them which represents a door, and call the open function on it if it does
// To use: Just assign a unique name to a door, and assign that name as a dynamic
// variable (attachedToDoor) for the trigger
datablock TriggerData(DoorTrigger)
{
   tickPeriodMS = 100;
   attachedToDoor = "";
};

// Lift the door
function DoorTrigger::onEnterTrigger(%this,%trigger,%obj)
{
	if (%trigger.attachedToDoor !$= "")
	{
		%door_id = nameToId(%trigger.attachedToDoor);
		if (%door_id != -1) 
			%door_id.getDataBlock().open(%door_id);
	}

	Parent::onEnterTrigger(%this,%trigger,%obj);
}

// Lower the door
function DoorTrigger::onLeaveTrigger(%this,%trigger,%obj)
{
   if (%trigger.attachedToDoor !$= "")
   {
	  %door_id = nameToId(%trigger.attachedToDoor);
	  if (%door_id != -1) 
	     %door_id.getDataBlock().close(%door_id);
   }

   Parent::onLeaveTrigger(%this,%trigger,%obj);
}

function DoorTrigger::onTickTrigger(%this,%trigger)
{
   Parent::onTickTrigger(%this,%trigger);
}



// use this trigger for doors which should act broken - not open enough for a person to go through
datablock TriggerData(BadDoorTrigger)
{
   tickPeriodMS = 500;
   attachedToDoor = "";
};

// Lift the door
function BadDoorTrigger::onEnterTrigger(%this,%trigger,%obj)
{
	if (%trigger.attachedToDoor !$= "")
	{
		%door_id = nameToId(%trigger.attachedToDoor);
		if (%door_id != -1) 
			%door_id.getDataBlock().badOpen(%door_id);
	}

	Parent::onEnterTrigger(%this,%trigger,%obj);
}

// Lower the door
function BadDoorTrigger::onLeaveTrigger(%this,%trigger,%obj)
{
   Parent::onLeaveTrigger(%this,%trigger,%obj);
}

function BadDoorTrigger::onTickTrigger(%this,%trigger)
{
	if (%trigger.attachedToDoor !$= "")
	{
		%door_id = nameToId(%trigger.attachedToDoor);
		if (%door_id != -1) 
			%door_id.getDataBlock().badOpen(%door_id);
	}
	
	Parent::onTickTrigger(%this,%trigger);
}









// Door sounds
datablock AudioProfile(DoorOpenSound)
{
	filename = "~/data/sound/dooropen.wav";
	description = AudioClose3d;
	preload = true;
};

datablock AudioProfile(DoorBadSound)
{
	filename = "~/data/sound/doorbad.wav";
	description = AudioClose3d;
	preload = true;
};

datablock AudioProfile(DoorCloseSound)
{
	filename = "~/data/sound/doorclose.wav";
	description = AudioClose3d;
	preload = true;
};




// These are Restricted access doors, or doors we want the user to use a key to open
// Ideally we wouldn't need more than the Door datablock, and we would just the doors
// skin when we need to display another type of door.  Unfortunately I didn't feel like
// redoing this door, and I'm using the two different door models someone else already
// made, which means I have to use two different dts files, and basically need two
// different doors
// IMPROVEMENT - schedule() returns an ID.  We should keep track of this ID when the
// Door::close() method is called.  Then, if the Door::open method is called before this event
// is fired, we'd cancel the close event.  
datablock StaticShapeData(Door)
{
   // The category variable determins where the item
   // shows up in the mission editor's creator tree.
   // Path is relative to where the script is executed from.
   category = "Door";
   shapeFile = "~/data/shapes/door/door.dts";
   doorLocked = false;
};

// Move a sliding door up
function Door::open(%this, %door)
{
	if (%door && %door.isOpen != true)
	{
		if (%door.doorLocked != true) // if a key is assigned to this door, its locked
		{
			if (!%door.isOpen)
			{
				schedule(10, 0, serverPlay3D, DoorOpenSound, %door.getTransform());
				//serverPlay3D(DoorOpenSound, %door.getTransform());
				// Store the doors current position for when we cose it
				%door.closedPosition = %door.position;
				// Set the z-index we want to stop at
				%door.openPosition = vectorAdd(%door.position, "0 0 4.4");
				schedule(10, %door, "OpenDoor", %door);
			}
		}
	}
}

// Simulate a broken door by only moving it up a tad, and then dropping it back down
function Door::badOpen(%this, %door)
{
	serverPlay3D(DoorBadSound, %door.getTransform());
	if (%door && %door.isOpen != true)
	{
		if (%door.doorLocked != true) // if a key is assigned to this door, its locked
		{
			if (!%door.isOpen)
			{
				// Store the doors current position for when we cose it
				%door.closedPosition = %door.position;
				// Set the z-index we want to stop at
				%door.openPosition = vectorAdd(%door.position, "0 0 0.5");
				schedule(10, %door, "OpenDoor", %door);
				schedule(200, %door, "CloseDoor", %door);
			}
		}
	}
}

// Moves a sliding door down
function Door::close(%this, %door)
{
	schedule(1100, 0, serverPlay3D, DoorCloseSound, %door.getTransform());
	schedule(1000, %door, "CloseDoor", %door);
}









// This represents doors which we don't want to be locked
datablock StaticShapeData(Door2 : Door)
{
   // The category variable determins where the item
   // shows up in the mission editor's creator tree.
   // Path is relative to where the script is executed from.
   category = "Door";
   shapeFile = "~/data/shapes/door/plaindoor.dts";
   doorLocked = false;
};

// Move a sliding door up
function Door2::open(%this, %door)
{
	Door::open(%this,%door);
}

// Simulate a broken door by only moving it up a tad, and then dropping it back down
function Door2::badOpen(%this, %door)
{
	Door::badOpen(%this,%door);
}

// Moves a sliding door down
function Door2::close(%this, %door)
{
	Door::close(%this,%door);
}











// We try to make the sliding pretty smooth, but we leave some gap time in the 
// animation scheduling for other tasks
function OpenDoor(%door)
{
	if (%door != -1 && door.isOpen == false)
	{
		%currZ = getWord(%door.position, 2);
		%openZ = getWord(%door.openPosition, 2);
		if (%currZ < %openZ)
		{
			%myNewPosition = vectorAdd(%door.position, "0 0 0.03");
			MoveObject(%door, %myNewPosition);
			schedule(3, %door, "OpenDoor", %door);
		}
		else
		{
			%door.isOpen = true;
		}
	}
}

// We don't spend many cycles closing the door because the player probably has their back turned to it, 
// and it doesn't need to be very smooth
function CloseDoor(%door)
{
	if (%door != -1 && %door.isOpen == true)
	{
		%currZ = getWord(%door.position, 2);
		%closedZ = getWord(%door.closedPosition, 2);
		if (%currZ > %closedZ)
		{
			%myNewPosition = vectorAdd(%door.position, "0 0 -0.5");
			MoveObject(%door, %myNewPosition);
			schedule(10, %door, "CloseDoor", %door);
		}
		else
		{
			%door.isOpen = false;
			// Ensure we're at the door's original Z position
			if (%currZ < %closedZ)
				MoveObject(%door, %door.closedPosition);
		}
	}
}

function MoveObject(%obj, %position)
{
   %Transform = %obj.getTransform();
   %Transform2 = %position @ "  " @ getWord(%Transform, 3);
   %obj.setTransform(%Transform2);
}